package com.lagou.sqlSession;


import com.lagou.pojo.Configuration;
import com.lagou.pojo.MappedStatement;

import java.lang.reflect.*;
import java.sql.SQLException;
import java.util.Collections;
import java.util.List;

public class DefaultSqlSession implements SqlSession {

    private Configuration configuration;

    public DefaultSqlSession(Configuration configuration) {
        this.configuration = configuration;
    }

    @Override
    public <E> List<E> selectList(String statementid, Object... params) throws ClassNotFoundException, SQLException, IllegalAccessException, NoSuchFieldException, InvocationTargetException, InstantiationException, javax.management.IntrospectionException {
        MappedStatement mappedStatement = configuration.getSqlMappedStatementMap().get(statementid);
        SimpleExecutor simpleExecutor = new SimpleExecutor();
        List<Object> list = simpleExecutor.query(configuration, mappedStatement, params);
        return (List<E>) list;
    }

    @Override
    public <T> T selectOne(String statementid, Object... params) throws ClassNotFoundException, SQLException, NoSuchFieldException, IllegalAccessException, InstantiationException, InvocationTargetException {
        List<Object> objects = null;
        try {
            objects = selectList(statementid, params);
        } catch (javax.management.IntrospectionException e) {
            e.printStackTrace();
        }
        if (objects.size() == 1) {
            return (T) objects.get(0);
        } else {
            throw new RuntimeException("结果集过多，或者不存在");
        }
    }


    @Override
    public void insert(String statementid, Object... params) throws ClassNotFoundException, SQLException, NoSuchFieldException, IllegalAccessException, InstantiationException, InvocationTargetException {
        MappedStatement mappedStatement = configuration.getSqlMappedStatementMap().get(statementid);
        SimpleExecutor simpleExecutor = new SimpleExecutor();
        try {
            simpleExecutor.insert(configuration, mappedStatement, params);
        } catch (javax.management.IntrospectionException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void update(String statementid, Object... params) throws ClassNotFoundException, SQLException, NoSuchFieldException, IllegalAccessException, InstantiationException, InvocationTargetException {
        MappedStatement mappedStatement = configuration.getSqlMappedStatementMap().get(statementid);
        SimpleExecutor simpleExecutor = new SimpleExecutor();
        try {
            simpleExecutor.update(configuration, mappedStatement, params);
        } catch (javax.management.IntrospectionException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void delete(String statementid, Object... params) throws ClassNotFoundException, SQLException, NoSuchFieldException, IllegalAccessException, InstantiationException, InvocationTargetException {
        MappedStatement mappedStatement = configuration.getSqlMappedStatementMap().get(statementid);
        SimpleExecutor simpleExecutor = new SimpleExecutor();
        try {
            simpleExecutor.delete(configuration, mappedStatement, params);
        } catch (javax.management.IntrospectionException e) {
            e.printStackTrace();
        }
    }

    @Override
    public <T> T getMapperClass(Class<?> mapperClass) {
        Object o = Proxy.newProxyInstance(DefaultSqlSession.class.getClassLoader(), new Class[]{mapperClass}, new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                // 底层还是执行了jdbc方法，proxy代理的对象，method具体执行方法，args传递的参数

                // 准备参数1 statementid
                String methodName = method.getName(); // 方法名
                String className = method.getDeclaringClass().getName();// 方法所在类
                String statementid = className + "." + methodName;

                // 准备参数2 params
                Type genericReturnType = method.getGenericReturnType(); // 获取调用方法的返回值类型
                // 判断类型是否进行了泛型化，如集合就是泛型
                if (genericReturnType instanceof ParameterizedType) {
                    List<Object> objects = selectList(statementid, args);
                    return objects;
                } else if (genericReturnType.getTypeName().equals("void") && methodName.startsWith("insert")) {
                    insert(statementid, args);
                    return Collections.emptyList();
                } else if (genericReturnType.getTypeName().equals("void") && methodName.startsWith("update")) {
                    update(statementid, args);
                    return Collections.emptyList();
                } else if (genericReturnType.getTypeName().equals("void") && methodName.startsWith("delete")) {
                    delete(statementid, args);
                    return Collections.emptyList();
                }
                return selectOne(statementid, args);
            }
        });
        return (T) o;
    }


}
